// vim: set et sw=4 ts=4 sts=4 fdm=marker ff=unix fenc=utf8 nobomb:
/**
 * tweets.js 
 *
 * Tweets Save Handle for Chrome
 *      Gears doesn't work in chrome addons, sigh~
 *
 * @author mingcheng<i.feelinglucky#gmail.com>
 * @date   2009-11-24
 * @link   http://www.gracecode.com/
 */

Tweets = (function() {
    var Util = YAHOO.util, Dom = Util.Dom, Event = Util.Event, Lang = YAHOO.lang;

    /**
     * 使用内存存储
     */
    var _data = new Object, _elements = new Object, _channels = [], _unread = [];

    /**
     * 最大范围
     */
    var MAX_STORAGE_LENGTH = 2000, MAX_LIST_NUMBER = 100;
    MAX_LIST_NUMBER = parseInt(Helper.Conf.Get('each_tab_size', MAX_LIST_NUMBER), 10);

    /**
     * 返回数组中唯一的值 {{{
     */
    var $unique = function(arr) {
        var a = [], l = arr.length;
        for(var i = 0; i < l; i++) {
            for(var j = i+1; j < l; j++) {
                // If this[i] is found later in the array
                if (arr[i] === arr[j])
                    j = ++i;
            }
            a.push(arr[i]);
        }
        return a;
    } // }}}

    /**
     * 将字符串分割为数组 {{{
     */
    var $split = function(str, length) {
        var len = str.length, loop = Math.ceil(len / length), result = [], i = 0;
        do {
            result.push(str.substr(i*length, length));
            i++;
        } while(i < loop);
        return result;
    } // }}}

    /**
     * 删除数组中的元素 {{{
     *      http://ejohn.org/blog/javascript-array-remove/
     */
    var $remove = function(arr, from, to) {
        var rest = arr.slice((to || from) + 1 || arr.length);
        arr.length = from < 0 ? arr.length + from : from;
        return arr.push.apply(arr, rest);
    }; // }}}

    /**
     * 合并并排序 // {{{
     */
    var $merge = function(target, source, sort) {
        source = source || []; target = target || [];
        source = source.concat(target); // concat two arrays

        // unique arrays
        for (var i = 0, len = source.length, matches = {}, tmp = []; i < len; i++) {
            var flag = source[i]['id'];
            if (matches['_' + flag]) { continue; }
            matches['_' + flag] = true;
            tmp.push(source[i]);
        }
        source = tmp;

        // sort by id
        if (typeof sort == 'undefined') sort = true;
        if (true || sort) { // always sort
            source = source.sort(function(a, b) {
                return (a['id'] > b['id']) ? -1 : 1;
            });
        }

        var max_tweets_number = parseInt(Helper.Conf.Get('max_tweets', MAX_LIST_NUMBER), 10);
        if (source.length > max_tweets_number) {
            console.warn('localStroage is limited, split the data');
            source.length = max_tweets_number;
        }

        return source;
    } // }}}

    /**
     * 比较两组数据，并返回不同值的个数 {{{
     */
    var diffResult = [], $diff = function(target, source) {
        try {
            var info = JSON.parse(Helper.Status.Get('twitter_info', []));
        } catch(e) {
            console.error('error: parse twitter_info error, use empty []');
            var info = [];
        }

        var matches = [], diff = 0;
        for (var i = 0, len = source.length; i < len; i++) {
            matches.push(parseInt(source[i]['id'], 10));
        }

        for (var i = 0, len = target.length; i < len; i++) {
            if (target[i]['user'] && info && info.id && info.id == target[i]['user']['id']) {
                continue;
            }
            if (matches.indexOf(target[i]['id']) == -1) {
                diffResult.push(parseInt(target[i]['id'], 10));
            }
        }

        diff = $unique(diffResult).length || 0;
        localStorage.setItem('status_unread_count', diff);
        return diff;
    } // }}}

    /**
     * 将数据保存到本地存储器
     */
    var $saveToLocal = function(name, data) {
        var storeArray = $split(JSON.stringify(data), MAX_STORAGE_LENGTH);
        localStorage.setItem(name + '_length', storeArray.length);
        for (var i = 0, length = storeArray.length; i < length; i++) {
            localStorage.setItem(name+'_'+i, storeArray[i]);
        }
    }

    /**
     * 清除指定名称的存储
     */
    var $clearList = function(name) {
        if (Lang.isArray(_data[name])) {
            _data[name].length = 0;
        }
        localStorage.setItem(name + '_length', '0');
    }

    /**
     * 将数据从本地存储器中取出
     */
    var $getFromLocal = function(name, data) {
        var length = parseInt(localStorage.getItem(name + '_length'), 10);
        for (var i = 0, result = ''; i < length; i++) {
            result += localStorage.getItem(name + '_' + i);
        }

        try {
            result = JSON.parse(result || '[]');
            return result;
        } catch (e) {
            console.error('parse localStorage data error');
            $clearList(name);
            return [];
        }
    }


    var handle = {
        addToList: function(name, data) {
            var source = this.getList(name);
            $diff(data, source); // diff new message
            _data[name] = $merge(data, source, false);
        },

        removeItem: function(id, name) {
            if (Lang.isUndefined(name)) {
                for(var i = 0, len = _channels.length, name = ''; i < len; i++) {
                    this.removeItem(id, _channels[i]);
                }
                return true;
            }

            if (Lang.isArray(_data[name])) {
                for(var i = 0, len = _data[name].length; i < len; i++) {
                    var item = _data[name][i];
                    if (!Lang.isUndefined(item) && id == item['id']) {
                        //return delete _data[name][i];
                        var result = $remove(_data[name], i);
                        if (result) {
                            $saveToLocal(name, _data[name]);
                        }
                        return result;
                    }
                }
            }

            return false;
        },

        getCombo: function() {
            for (var i = 0, result = [], len = arguments.length; i < len; i++) {
                result = $merge(result, this.getList(arguments[i]), true);
            }
            return result;
        },

        modifyItem: function(name, data) {
            if (Lang.isObject(data)) {
                var list = this.getList(name);
                for(var i = 0, len = list.length; i < len; i++) {
                    if (data['id'] == list[i]['id']) {
                        list[i] = data;
                        return true;
                    }
                }
            }
            return false;
        },

        getUnreadNum: function() {
            return localStorage.getItem('status_unread_count') || 0;
        },

        getUnreadArray: function() {
            return $unique(diffResult);
        },

        sync: function() {
            for(var i = 0, len = _channels.length, name = ''; i < len; i++) {
                name = _channels[i];
                $saveToLocal(name, _data[name]);
            }
        },

        clearUnreadNum: function() {
            diffResult.length = 0;
            localStorage.setItem('status_unread_count', 0);
        },

        getList: function(name, enforce) {
            if (_channels.indexOf(name) == -1) {
                _channels.push(name);
            }
            if (!enforce && Lang.isArray(_data[name])) {
                return _data[name];
            }

            var data = $getFromLocal(name); _data[name] = data;
            return _data[name];
        },

        clearList: $clearList
    };

    return handle;
})();
